#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <curl/curl.h>
#include "cJSON/cJSON.h"
#include "data_type.h"
#include "myfunc.h"
//************************************************************************************
//	全局变量
//************************************************************************************

extern pthread_mutex_t sys_pages_lock;			//详细信息队列互斥锁
extern pthread_mutex_t error_file_lock;			//错误文件互斥锁
extern struct order_page_node *sys_order_pages;		//获取到的详细信息加入到调度令信息队列
extern struct int_queue_node *sys_order_id_unread;	//未获取信息队列id
extern char jsessionid_ptr[100];			//cookie: jessionid 值
extern char remember_ptr[1025];				//cookie: rememberMe 值
//extern struct int_queue_node* id_queue;

//libcurl 回调函数
size_t http_body_rsps(char*,size_t,size_t,void*);
size_t http_header_rsps(char*,size_t,size_t,void*);


//************************************************************************************
//	http 线程
//************************************************************************************
void * http_thread_proc(void * argument){
	pthread_detach(pthread_self());
	//***************************************************************************
	//	set up var
	//***************************************************************************
	//	这些变量需要初始化及销毁
	struct data_buffer body_tmp[2];		//连续两次的http内容
	struct data_buffer header_tmp[2];	//连续两次的http头部
	struct data_buffer http_response_body;	//http回调函数参数
	struct data_buffer http_response_header;//http回调函数参数
	struct curl_slist *header;		//
	CURL *handle;				// curl 句柄
	struct order_page new_page;
	//*********************************************************************************
	//***************************************************************************
	CURLcode curl_code;			// http请求结果
	struct http_thread_arg *arg;
	char url[100];				//url
	char post_data[100];			// post 数据
	int exception_retry_times;		//
	int order_id;				//
	char cookie_str[1024];			// cookie
	int http_ok;
	char *html_data;			//
	int error_num;				//故障码
	//***************************************************************************
	//	initial var
	//***************************************************************************
	arg=argument;
	//	赋值后无需再初始化
	new_page=arg->page_info;
	//order_page_init(&new_page);	
	handle=curl_easy_init();
	order_id=(arg->page_info).tb_order_id;	//本次要获取的调度令的id
	header=NULL;
	memset(cookie_str,0,1024);
	memset(url,0,100);
	memset(post_data,0,100);
	http_ok=0;
	html_data=NULL;
	for(int i=0;i<2;i++){
		data_buffer_init_1k(&body_tmp[i]);
		data_buffer_init_1k(&header_tmp[i]);
	}
	data_buffer_init_1k(&http_response_body);
	data_buffer_init_1k(&http_response_header);


	//*********************************************************************************
	//	http2请求参数设置 获取调度令详细信息
	//*********************************************************************************
	//	url
printf("enter http\n");
	sprintf(url,"http://%s/oprt-order-op/oprt-order-op-list-load.action?id=%d","10.12.3.23",order_id);
	curl_easy_setopt(handle,CURLOPT_URL,url);
	//	post method
	curl_easy_setopt(handle,CURLOPT_POST,1L);
	curl_easy_setopt(handle,CURLOPT_TIMEOUT,20L);
	curl_easy_setopt(handle,CURLOPT_CONNECTTIMEOUT,20L);
	//	http post data
	strcpy(post_data,"_search=false&nd=170674596366&rows=10&page=1&sidx=&sord=asc");
	curl_easy_setopt(handle,CURLOPT_POSTFIELDS,post_data);
	curl_easy_setopt(handle,CURLOPT_POSTFIELDSIZE,strlen(post_data));
	//	http header
	curl_slist_free_all(header);
	header=NULL;
	header=curl_slist_append(header,"Accept: */*");
	header=curl_slist_append(header,"Accept-Encoding: gzip, deflate");
	header=curl_slist_append(header,"Content-Type: application/x-www-form-urlencoded");
	curl_easy_setopt(handle,CURLOPT_HTTPHEADER,header);
	//	http cookie
	strcpy(cookie_str,jsessionid_ptr);
	strcat(cookie_str,"; ");
	strcat(cookie_str,remember_ptr);
	curl_easy_setopt(handle,CURLOPT_COOKIE,cookie_str);
	//	callback function
	curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,http_body_rsps);
	curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,http_header_rsps);
	curl_easy_setopt(handle,CURLOPT_WRITEDATA,&http_response_body);
	curl_easy_setopt(handle,CURLOPT_HEADERDATA,&http_response_header);
	//***********************************************************************************
	//	send http request
	//***********************************************************************************
	exception_retry_times=6;
	while(exception_retry_times--){
		data_buffer_reset_1k(&http_response_body);
		data_buffer_reset_1k(&http_response_header);
		for(int i=0;i<http_ok;i++){
			data_buffer_reset_1k(&body_tmp[i]);
			data_buffer_reset_1k(&header_tmp[i]);
		}
		http_ok=0;
		//	获取连续两次成功请求的结果,结果放在body_tmp[i]和header_tmp[i]
		while(http_ok < 2){
			curl_code=curl_easy_perform(handle);
			//读取成功后保存数据，再次读取
			if( curl_code == CURLE_OK ){
				data_buffer_duplicate(&body_tmp[http_ok],&http_response_body);
				data_buffer_duplicate(&header_tmp[http_ok],&http_response_header);
				http_ok++;
				data_buffer_reset_1k(&http_response_body);
				data_buffer_reset_1k(&http_response_header);
				usleep(200);
				continue;
			}
			else{
				data_buffer_reset_1k(&http_response_body);
				data_buffer_reset_1k(&http_response_header);
				break;	//跳到这个while
			}
		}
		//*****************************************************************************************
		//	2 success and same response
		//*****************************************************************************************
		if( http_ok == 2 ){	//连续两次成功的html响应
			if(data_buffer_equal(&body_tmp[0],&body_tmp[1])){
				html_data=malloc(body_tmp[0].dataSize+1);
				strcpy(html_data,body_tmp[0].contentPtr);
				for(int i=0;i<2;i++){
					data_buffer_reset_1k(&body_tmp[i]);
				}
				if(json_to_order_page(html_data,&new_page)){
				//	获取详细信息成功，写入队列
			printf("html ok%u\n",new_page.tb_order_id);
					pthread_mutex_lock(&sys_pages_lock);
						add_order_pages(sys_order_pages,&new_page);
					pthread_mutex_unlock(&sys_pages_lock);
					//order_page_destroy(&new_page);
					//order_page_init(&new_page);
					free(html_data);
					//	数据获取成功，跳过写文件
					break;	//跳出while 到达CHECK2
				}else{	//html内容无法匹配到json文件,再循环读取
					for(int i=0;i<2;i++){
						data_buffer_reset_1k(&body_tmp[i]);
					}
					order_page_destroy(&new_page);
					order_page_init(&new_page);
					free(html_data);
				}
			}else{//	两次数据不一致，清空临时变量,再来一次
				for(int i=0;i<2;i++){
					data_buffer_reset_1k(&body_tmp[i]);
					data_buffer_reset_1k(&header_tmp[i]);
				}
			}
		}else{	//不是连续成功的http读取，延时后再次请求
			sleep(2);
		}
	}
CHECK2:
	//	cleanup
	//
	curl_slist_free_all(header);
	curl_easy_cleanup(handle);
	data_buffer_destroy(&http_response_body);
	data_buffer_destroy(&http_response_header);
	for(int i=0;i<2;i++){
		data_buffer_destroy(&body_tmp[i]);
		data_buffer_destroy(&header_tmp[i]);
	}
	order_page_destroy(&new_page);
	free(argument);

	//	返回处理
	if(exception_retry_times==-1){	//获取数据失败
		time_t current_time;
		time(&current_time);
		printf("html failed%u\n",order_id);
		pthread_mutex_lock(&error_file_lock);
		FILE *fp=fopen("./log/error_ids","a");
		fprintf(fp,"%s %u %u\n",ctime(&current_time),order_id,error_num);
		fclose(fp);
		pthread_mutex_unlock(&error_file_lock);
		printf("get order info failed %u\n",order_id);
		pthread_exit(NULL);
		return NULL;
	}
	else{	//获取数据成功
		pthread_exit(NULL);
		return NULL;
	}
}

//**************************************************************************************
//	回调函数
//**************************************************************************************
size_t http_body_rsps(char* text,size_t block_size,size_t block_count,void* userdata){
	struct data_buffer *tmp=userdata;
	add_data(tmp,text,block_count*block_size);
	return block_count*block_size;
}

//**************************************************************************************
//	回调函数
//**************************************************************************************
size_t http_header_rsps(char* text,size_t block_size,size_t block_count,void* userdata){
	struct data_buffer *tmp=userdata;
	add_data(tmp,text,block_count*block_size);
	return block_count*block_size;
}

